package com.mikelouis.test.scala.proginscala.chapter6

/**
 * Created by yuazhu on 12/19/2014.
 */
// n & d: 类参数
// 尽管n和d是用在类的函数体内，因为他们只是用在构造器之内，Scala编译器将不会为它们自动构造域。所以就这些代码来说，Scala编译器将产生一个有两个Int域的类，一个是numer，另一个是denom
class Rational(n: Int, d: Int) {
  // require方法带一个布尔型参数。如果传入的值为真，require将正常返回。反之，require将通过抛出IllegalArgumentException来阻止对象被构造
  require(d != 0)

  /** Scala编译器将把Rational的三个字段的初始化代码依照它们在源代码中出现的次序放入主构造器 */
  // 分数进行约简化
  private val g = gcd(n.abs, d.abs)

  // 字段
  val numer: Int = n / g
  val denom: Int = d / g

//  println("Created " + numer + "/" + denom)

  /** constructor overloading */
  def this(n: Int) = this(n, 1)


  override def toString: String = numer + "/" + denom

  def add(that: Rational): Rational = {
    new Rational(numer * that.denom + that.numer * denom, denom * that.denom)
  }

  def lessThan(that: Rational): Boolean = this.numer * that.denom < that.numer * this.denom

  def max(that: Rational): Rational = if (this.lessThan(that)) that else this

  private def gcd(a: Int, b: Int): Int = {
    if (b == 0) a else gcd(b, a % b)
  }

  /** defining operator */
  def +(that: Rational): Rational = {
    new Rational(numer * that.denom + that.numer * denom, denom * that.denom)
  }

  // overload method
  def +(i: Int): Rational = new Rational(numer + i * denom, denom)

  def -(that: Rational): Rational = new Rational(numer * that.denom - that.numer * denom, denom * that.denom)

  def -(i: Int): Rational = new Rational(numer - i * denom, denom)

  def *(that: Rational): Rational = {
    new Rational(numer * that.numer, denom * that.denom)
  }

  def *(i: Int): Rational = new Rational(numer * i, denom)

  def /(that: Rational): Rational = new Rational(numer * that.denom, denom * that.numer)

  def /(i: Int): Rational = new Rational(numer, denom * i)

}
